package org.zxyj.manage.service.impl;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.zxyj.core.constants.SysParamsDict;
import org.zxyj.core.entity.Pagination;
import org.zxyj.core.utils.Common;
import org.zxyj.core.utils.MessageUtil;
import org.zxyj.manage.dao.ICourseObjectiveAnswerDao;
import org.zxyj.manage.dao.ICoursePaperDao;
import org.zxyj.manage.dao.ICourseTemplateDao;
import org.zxyj.manage.dao.IMarkingPaperDao;
import org.zxyj.manage.entity.CourseObjectiveAnswer;
import org.zxyj.manage.entity.CoursePaperCrop;
import org.zxyj.manage.entity.CoursePaperCropTmxx;
import org.zxyj.manage.entity.CoursePaperDetail;
import org.zxyj.manage.entity.CourseTemplateArea;
import org.zxyj.manage.service.ICropService;
import org.zxyj.manage.service.IMarkingPaperService;
import org.zxyj.manage.service.IPointRecognitionService;
import org.zxyj.system.domain.User;

@Service
public class IMarkingPaperServiceImpl implements IMarkingPaperService{
	protected Logger logger = LoggerFactory.getLogger(this.getClass());
	//读取配置文件
    //private static PropertiesUtil configProp = PropertiesUtil.newInstance(Thread.currentThread().getContextClassLoader().getResource("").getPath() + "config/config.properties");
	@Autowired
	private IMarkingPaperDao dao;
	@Autowired
	private ICourseObjectiveAnswerDao answerDao;
	@Autowired
	private ICourseTemplateDao courseTemplateDao;
	@Autowired
    private ICropService cropService;
    @Autowired
    private IPointRecognitionService pointRecognitionService;
    @Autowired
	private ICoursePaperDao coursePaperDao;

	public Pagination findMarkingPaperObjectivePage(Map<String, Object> criteria, Pagination pagination) {
		logger.debug("listing entities refer to criteria and pagination, param: criteria[{}], pagination[{}]", criteria, pagination);
		if (null == criteria) {
			criteria = new HashMap<String, Object>();
		}
		criteria.put("pagination", pagination);
		if (null == pagination) {
			pagination = new Pagination();
		}
		criteria.put("userId", Common.findUserSessionId());
		pagination.setDatas(this.dao.findMarkingPaperObjectiveList(criteria));
		pagination.setTotal(this.dao.findMarkingPaperObjectiveCount(criteria));
		return pagination;
	}
	
	public Pagination findMarkingPaperObjectiveStudentPage(Map<String, Object> criteria, Pagination pagination){
		logger.debug("listing entities refer to criteria and pagination, param: criteria[{}], pagination[{}]", criteria, pagination);
		if (null == criteria) {
			criteria = new HashMap<String, Object>();
		}
		criteria.put("pagination", pagination);
		if (null == pagination) {
			pagination = new Pagination();
		}
		criteria.put("userId", Common.findUserSessionId());
		pagination.setDatas(this.dao.findMarkingPaperObjectiveStudentList(criteria));
		pagination.setTotal(this.dao.findMarkingPaperObjectiveStudentCount(criteria));
		return pagination;
	}

	public void objectiveAnswerRecognition(Map<String,Object> params) {
		HttpSession session = (HttpSession) params.get("session");
		int succCount=0;//记录成功数
        int failCount=0;//记录失败数
        int clzs=0;//处理总数
        int kgtsl=0;//客观题区域块数量
        String resultCode = SysParamsDict.STATUS_CODE.SUCCESS.getValue();
        String courseTemplateId = (String) params.get("courseTemplateId");
        //String userId = Common.findUserSessionId();
        
        //查询科目客观题答案
        Map<String,String> answerMap = new HashMap<String,String>();
        Map<String,Object> criteria = new HashMap<String,Object>();
        criteria.put("owner", courseTemplateId);
        List<CourseObjectiveAnswer> answerList = this.answerDao.find(criteria);
        if(!CollectionUtils.isEmpty(answerList)){
        	for(CourseObjectiveAnswer e : answerList){
        		answerMap.put(e.getTh(), e.getDa());
        	}
        }else{
        	resultCode = SysParamsDict.CHECK_STATUS_CODE.NO_ANSWER.getValue();
        }
        
        if(!answerMap.isEmpty()){
        	//重新计算客观题之前需要先删除已有数据
            deleteObjectScore(params);
            
            //查询科目模板所有切割区域
            criteria.put("courseTemplateId", courseTemplateId);
        	String[] lxArr = {"3","4","6"};
        	criteria.put("lxList", Arrays.asList(lxArr));
            List<CourseTemplateArea> areaList =this.courseTemplateDao.getCourseTemplateAreaList(criteria);
            if(!CollectionUtils.isEmpty(areaList)){
            	Map<String,CourseTemplateArea> areaMap = new HashMap<String,CourseTemplateArea>();//选择题
                Map<String,Integer> kgtttMap = new HashMap<String,Integer>();//客观题填涂区
                Map<String,Float> fzcsMap = new HashMap<String,Float>();
                for(CourseTemplateArea a : areaList){
                	//获取模板定位区截图信息
                	String lx = a.getLx();//区域类型
                	if("3".equals(lx)){//客观题单选区域
                		areaMap.put(a.getId(), a);
                        fzcsMap.put("dtfzSin", Float.parseFloat(a.getDtfz()));//单题分值
                        kgtsl++;
                	}else if("4".equals(lx)){//客观题多选区域
                		areaMap.put(a.getId(), a);
                        fzcsMap.put("dtfzMore", Float.parseFloat(a.getDtfz()));//单题分值
                        fzcsMap.put("lxfzMore", Float.parseFloat(a.getDtfzlx()));//单题漏选分值
                        kgtsl++;
                	}else{//客观题填涂区
                        kgtttMap.put("areaWidth", a.getAreaWidth()==null?0:a.getAreaWidth());
                        kgtttMap.put("areaHeight", a.getAreaHeight()==null?0:a.getAreaHeight());
                	}
                }
                
                //解析识别客观题答卷
                criteria.clear();
                criteria.put("status", 0);
                criteria.put("courseTemplateId", courseTemplateId);
                int[] typeArr = {3,4};
                criteria.put("types", typeArr);
                List<CoursePaperCrop> cropList = this.coursePaperDao.findCoursePaperCropList(criteria);
                if(!CollectionUtils.isEmpty(cropList)){
                	session.setAttribute("djzs_objective", cropList.size()==0 || kgtsl==0?0:cropList.size()/kgtsl);
                	//识别客观题答案-单个小区域
                	for(CoursePaperCrop c : cropList){
                        try{
                        	BufferedImage image = this.cropService.readImageBuffered(MessageUtil.getExtConfig("fj.course.paper.crop.url") + c.getFilePath());//读取文件流
                            Map<String, String> resultMap = this.pointRecognitionService.recognitionObjectiveAnswer(image,areaMap.get(c.getAreaId()),kgtttMap);//识别答案结果
                            //比对答案结果计算分值
                            if(!answerMap.isEmpty()){
                            	Map<String,Object> param = new HashMap<String,Object>();
                                param.put("cropId", c.getId());
                                param.put("type", c.getType());
                                param.put("owner", c.getOwner());
                                computerObjectiveScore(param,resultMap,answerMap,fzcsMap);
                            }
                            image = null;
                            succCount++;
                        }catch(Exception e){
                        	logger.info("CoursePaperCrop is Recognition exception!!!!!!!", e);
                            failCount++;
                        }
                        clzs++;
                        session.setAttribute("clzs_objective", clzs==0 || kgtsl==0?0:clzs/kgtsl);
                	}
                }
            }else{
            	resultCode = SysParamsDict.CHECK_STATUS_CODE.NO_OBJECTIVE.getValue();
            }
        }
        
        session.setAttribute("failCount_objective", failCount==0 || kgtsl==0?0:failCount/kgtsl);
        session.setAttribute("succCount_objective", succCount==0 || kgtsl==0?0:succCount/kgtsl);
        session.setAttribute("resultCode_objective", resultCode);
	}
	
	/**
	 * 比对计算答案结果
	    * @Title: computerObjectiveScore
	    * @param @param param
	    * @param @param resultMap
	    * @param @param answerMap
	    * @param @param fzcsMap    参数
	    * @return void    返回类型
	    * @throws
	 */
	public void computerObjectiveScore(Map<String,Object> param,Map<String, String> resultMap,Map<String,String> answerMap,Map<String,Float> fzcsMap){
        String cropId = (String) param.get("cropId");
        String owner = (String) param.get("owner");
        int type = Integer.parseInt(param.get("type")+"");
        float dtfzSin = fzcsMap.containsKey("dtfzSin")?fzcsMap.get("dtfzSin"):0f;
        float dtfzMore = fzcsMap.containsKey("dtfzMore")?fzcsMap.get("dtfzMore"):0f;
        float lxfzMore = fzcsMap.containsKey("lxfzMore")?fzcsMap.get("lxfzMore"):0f;
        
        //循环所有区域结果集
        boolean sinFlag = false;//是否含有单选
        boolean moreFlag = false;//是否含有多选
        Map<String, Float> cropResultMap = new HashMap<String, Float>();//存放所有题目小块总分
        Map<String, Float> singleScoreMap = new HashMap<String,Float>();//考生单题得分结果集
        Map<String, String> stuSingleScoreMap = new HashMap<String,String>();//考生单题答案结果集
        float cropScore = 0.0f;//题目小块总分值
        for(Entry<String, String> entry : resultMap.entrySet()){
        	String th = entry.getKey();//题号
            String val = entry.getValue().toUpperCase();//答案结果
            float score = 0.0f;//单题得分
            String bzda = answerMap.containsKey(th)?answerMap.get(th):"";//标准答案
            int bzdasl = bzda.length();//标准答案长度
            if(type==3){//单选
                if(val.equalsIgnoreCase(bzda)){ //结果正确
                	score = dtfzSin;
                }
                sinFlag = true;
            }else{ //多选:判断多选的几种情况
                if(!StringUtils.isEmpty(val)){//答案不为空情况
                    String[] das = val.split(",");
                    int zqsl = 0;//正确答案数量
                    for(int a=0;a<das.length;a++){
                        //判断每个值是否存在于标准答案中
                        if(bzda.contains(das[a].toUpperCase())){
                            zqsl++;
                        }else{//结果不正确,包含错误答案，判错
                        	score = 0f;
                            break;
                        }
                    }
                    //判断正确答案是否全部匹配
                    if(zqsl > 0){
                        if(bzdasl==zqsl){//全匹配按单题分计算
                        	score = dtfzMore;
                        }else{//部分匹配按漏选分值计算
                        	score = lxfzMore;
                        }
                    }
                    val = val.replace(",", "");
                }
                moreFlag = true;
            }
            
            cropScore += score;//计算小块总得分
            singleScoreMap.put(th, score);
            stuSingleScoreMap.put(th, val);
        }
        
        cropResultMap.put(cropId, cropScore);//存放小块总分值
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("cropId", cropId);
        map.put("owner", owner);
        map.put("sinFlag", sinFlag);
        map.put("moreFlag", moreFlag);
        map.put("singleScoreMap", singleScoreMap);
        map.put("stuSingleScoreMap", stuSingleScoreMap);
        map.put("cropResultMap", cropResultMap);
        saveCropResult(map);
	}
	
	@SuppressWarnings("unchecked")
	@Transactional(rollbackFor = Exception.class)
	public void saveCropResult(Map<String,Object> map){
		this.insertCropTmxx(map);//保存单题小项分值
        this.updateCropScore((Map<String, Float>)map.get("cropResultMap"));//更新裁剪小块总分值
        this.updatePaperDetail(map);//更新考生答卷客观题阅卷信息
	}
	
	/**
	 * 保存小题目分数信息
	    * @Title: insertCropTmxx
	    * @param @param map    参数
	    * @return void    返回类型
	    * @throws
	 */
	@SuppressWarnings("unchecked")
	public void insertCropTmxx(Map<String, Object> map){
		Map<String, Float> singleScoreMap = (Map<String, Float>) map.get("singleScoreMap");
		Map<String, String> stuSingleScoreMap = (Map<String, String>) map.get("stuSingleScoreMap");
		if(!singleScoreMap.isEmpty()){
			for(Map.Entry<String, Float> entry : singleScoreMap.entrySet()){
				CoursePaperCropTmxx entity = new CoursePaperCropTmxx();
				entity.setOwner(map.get("cropId")+"");
				entity.setTh(entry.getKey());
				entity.setVal(stuSingleScoreMap.get(entry.getKey()));
				entity.setScore(entry.getValue()+"");
				User user = (User) Common.findUserSession();
				entity.setCreator(user);
				this.coursePaperDao.insertCoursePaperCropTmxx(entity);
			}
		}
	}
	
	/**
	 * 更新裁剪小块总分值
	    * @Title: saveCropScore
	    * @param @param params    参数
	    * @return void    返回类型
	    * @throws
	 */
	public void updateCropScore(Map<String, Float> params){
		if(!params.isEmpty()){
			for(Map.Entry<String, Float> entry : params.entrySet()){
                CoursePaperCrop entity = new CoursePaperCrop();
                entity.setId(entry.getKey());
                entity.setStatus(1);
                entity.setScore(entry.getValue()+"");
                User user = (User) Common.findUserSession();
                entity.setOperator(user);
                this.coursePaperDao.updateCropScore(entity);
			}
		}
	}
	
	/**
	 * /更新考生答卷客观题阅卷信息
	    * @Title: updatePaperDetail
	    * @param @param owner
	    * @param @param sinFlag
	    * @param @param moreFlag    参数
	    * @return void    返回类型
	    * @throws
	 */
	public void updatePaperDetail(Map<String,Object> map){
		boolean sinFlag = (boolean) map.get("sinFlag");
		boolean moreFlag = (boolean) map.get("moreFlag");
		int single = 0,mulitple = 0;
        if(sinFlag){
        	single = 1;
        }
        if(moreFlag){
        	mulitple = 1;
        }
        CoursePaperDetail entity = new CoursePaperDetail();
        entity.setStatusSingle(single);
        entity.setStatusMultiple(mulitple);
        entity.setId(map.get("owner")+"");
        this.coursePaperDao.updatePaperDetail(entity);
	}
	
	/**
	 * 删除客观题得分信息,重新计算客观题之前需要先删除已有数据
	    * @Title: deleteObjectScore
	    * @param @param courseTemplateId    参数
	    * @return void    返回类型
	    * @throws
	 */
	@Transactional(rollbackFor = Exception.class)
	public void deleteObjectScore(Map<String,Object> criteria){
		List<String> tempIds = new ArrayList<String>();
		tempIds.add(criteria.get("courseTemplateId")+"");
		criteria.put("tempIds", tempIds);
		this.coursePaperDao.clearPaperCropTmxx(criteria);
		this.coursePaperDao.updateCropScoreByTempId(criteria);
		this.coursePaperDao.updatePaperDetailByTempId(criteria);
	}

	public List<Map<String, Object>> findMarkingPaperObjectiveStudentScore(Map<String, Object> criteria) {
		logger.debug("listing entities refer to criteria and param: criteria[{}], pagination[{}]", criteria);
		if (null == criteria) {
			criteria = new HashMap<String, Object>();
		}
		return this.dao.findMarkingPaperObjectiveStudentScore(criteria);
	}
	
	/**********************主观题阅卷部分***********************/
	public Pagination findMarkingPaperSubjectiveGroupPage(Map<String, Object> criteria, Pagination pagination) {
		logger.debug("listing entities refer to criteria and pagination, param: criteria[{}], pagination[{}]", criteria, pagination);
		if (null == criteria) {
			criteria = new HashMap<String, Object>();
		}
		criteria.put("pagination", pagination);
		if (null == pagination) {
			pagination = new Pagination();
		}
		criteria.put("userId", Common.findUserSessionId());
		pagination.setDatas(this.dao.findMarkingPaperSubjectiveGroupList(criteria));
		pagination.setTotal(this.dao.findMarkingPaperSubjectiveGroupCount(criteria));
		return pagination;
	}

	public Pagination findSubjectiveDetailByAreaIdPage(Map<String, Object> criteria, Pagination pagination) {
		logger.debug("listing entities refer to criteria and pagination, param: criteria[{}], pagination[{}]", criteria, pagination);
		if (null == criteria) {
			criteria = new HashMap<String, Object>();
		}
		criteria.put("pagination", pagination);
		if (null == pagination) {
			pagination = new Pagination();
		}
		pagination.setDatas(this.dao.findSubjectiveDetailByAreaIdList(criteria));
		pagination.setTotal(this.dao.findSubjectiveDetailByAreaIdCount(criteria));
		return pagination;
	}

	@Transactional(rollbackFor = Exception.class)
	public void initSubjectiveTmxx(Map<String, Object> criteria) {
		this.dao.initSubjectiveTmxx(criteria);
	}

}
